#pragma once

#include <unordered_map>
class reactor;
#include "Epoller.hpp"
#include "Connection.hpp"

// 提供对connection的管理工作
// 如果有对应的fd就绪，就对其进行通知
// 事件派发器
class reactor
{
    const static int gnum = 64;

private:
    bool connectionIsExists(int fd)
    {
        return _connections.count(fd);
    }

    void onceLoop(int n)
    {
        for (int i = 0; i < n; i++)
        {
            int fd = ready_events[i].data.fd;
            uint32_t event = ready_events[i].events;

            // 将错误都归结到读写上
            // 再在读写中统一处理错误异常
            if (event & EPOLLHUP)
                event |= (EPOLLIN | EPOLLOUT);
            if (event & EPOLLERR)
                event |= (EPOLLIN | EPOLLOUT);
            if (event & EPOLLIN) // 读就绪
            {
                if (connectionIsExists(fd) && _connections[fd]->_recever != nullptr)
                    _connections[fd]->_recever(_connections[fd]);
            }
            if (event & EPOLLOUT) // 写就绪
            {
                if (connectionIsExists(fd) && _connections[fd]->_sender != nullptr)
                    _connections[fd]->_sender(_connections[fd]);
            }
        }
    }

public:
    reactor()
    {
    }

    void addConnection(int fd, uint32_t event, func_t recever, func_t sender, func_t excepter)
    {
        // 构建connection对象
        connection *conn = new connection(fd);
        conn->Register(recever, sender, excepter);
        conn->setReactor(this);
        conn->setEvent(event);

        // 向epoll模型中添加对fd及其事件的关心
        e.addFdAndEvent(conn->getFd(), conn->getEvent());

        // 向Reactor中添加connection对象
        _connections.insert(std::make_pair(fd, conn));
    }

    void delConnection(int fd)
    {
        if (connectionIsExists(fd))
        {
            e.delFdEvent(fd);               //1.从底层epoll删除
            _connections[fd]->closeFd();    //2.关闭fd
            delete _connections[fd];        //3.释放资源
            _connections.erase(fd);         //4.从_connections集合中删除
        }
    }

    void enableReadWirte(int fd, bool read, bool write)
    {
        uint32_t event = (read ? EPOLLIN : 0) | (write ? EPOLLOUT : 0) | EPOLLET;

        if (connectionIsExists(fd))
        {
            _connections[fd]->setEvent(event); // 修改管理的connection
            e.changeFdEvent(fd, event);        // 修改内核epoll
        }
    }

    // 事件派发核心函数
    void dispatcher()
    {
        int timeout = -1;
        while (true)
        {
            int n = e.wait(ready_events, gnum, timeout);
            onceLoop(n);
        }
    }

    ~reactor()
    {
    }

private:
    std::unordered_map<int, connection *> _connections; // 以fd为键值，存储所有的连接
    epoller e;
    epoll_event ready_events[gnum];
};